#define _GNU_SOURCE
#define MAX 700

#include "../include/head.h"

int zeroCpySend(int clientFd, char *fileName)
{
    //采用“零拷贝”的方式根据请求发送不定长的文件
    Train_t train;
    //1、先发送文件名
    train.dataLen = strlen(fileName);
    memcpy(train.buf, fileName, train.dataLen);
    send(clientFd, &train, 4 + train.dataLen, 0);    // 把文件名发过去
    
    //2、打开文件，读取并发送
    int fd = open(fileName, O_RDWR);
    ERROR_CHECK(fd, -1, "open");

    //获取文件信息  并把文件总大小发送给客户端
    struct stat fileInfo;
    fstat(fd, &fileInfo);
    train.dataLen = sizeof(fileInfo.st_size);
    memset(train.buf, 0, sizeof(train.buf));
    memcpy(train.buf, &fileInfo.st_size, train.dataLen);
    send(clientFd, &train, 4 + train.dataLen, 0);

    //零拷贝传输接口 1：mmap
    /* char *pMap = (char *)mmap(0, fileInfo.st_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); */
    /* ERROR_CHECK(pMap, (char *)-1, "mmap"); */
    /* int sendRet = send(clientFd, pMap, fileInfo.st_size, 0); */
    /* ERROR_CHECK(sendRet, -1, "send"); */
    /* munmap(pMap, fileInfo.st_size); */

    //零拷贝接口 2：sendfile
    /* int sendRet = sendfile(clientFd, fd, 0, fileInfo.st_size); */
    /* ERROR_CHECK(sendRet, -1, "sendfile"); */

    //零拷贝接口 3：splice
    //需要借助管道
    int fdPipe[2];
    pipe(fdPipe);
    ssize_t sendRet = 0;
    ssize_t sendSize = 0;

    while(sendSize < fileInfo.st_size){
        //循环从文件中读出，然后通过管道发送个客户端
        sendRet = splice(fd, 0, fdPipe[1], 0, MAX, 0);
        sendRet = splice(fdPipe[0], 0, clientFd, 0, MAX, 0);
        if(-1 == sendRet){
            //连接断了，直接返回！
            printf("client exit!\n");
            /* break; */
            return -1;
        }
        sendSize += sendRet;
    }

    return 0;
}

